﻿using IOP.SgrA.GLSL;
using IOP.SgrA.SilkNet.Vulkan;
using IOP.SgrA.SilkNet.Vulkan.Scripted;
using Silk.NET.Vulkan;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace VkSample121
{
    [ShaderVersion("460")]
    [GLSLExtension("GL_ARB_separate_shader_objects : enable")]
    [GLSLExtension("GL_ARB_shading_language_420pack : enable")]
    public partial class TexLightVert : GLSLVert
    {
        [UniformBuffer(0, 0, DescriptorSetTarget.Pipeline)]
        public BufferVals Vals {  get; set; }
        [PushConstant(128, 0)]
        public ConstantVals MyConstantVals {  get; set; }

        [VertInput(0, Format.R32G32B32Sfloat)]
        public vec3 Pos { get; set; }
        [VertInput(1, Format.R32G32B32Sfloat)]
        public vec3 InNormal {  get; set; }
        [VertInput(2, Format.R32G32Sfloat)]
        public vec2 ALongLat {  get; set; }

        [ShaderOutput(0)]
        public vec4 outLightQD {  get; set; }
        [ShaderOutput(1)]
        public vec2 mcLongLat {  get; set; }

        public override void main()
        {
            outLightQD = pointLight(MyConstantVals.mm, Vals.uCamera.xyz, Vals.lightPosition.xyz,
                        Vals.lightAmbient, Vals.lightDiffuse, Vals.lightSpecular,
                        InNormal, Pos);
            gl_Position = MyConstantVals.mvp * new vec4(Pos, 1.0f);//计算最终的顶点位置 
            mcLongLat = ALongLat;//把顶点经纬度传给片元着色器
        }

        private vec4 pointLight([In] mat4 uMMatrix, [In] vec3 uCamera, [In] vec3 lightLocation, 
            [In] vec4 lightAmbient, [In] vec4 lightDiffuse, [In] vec4 lightSpecular, [In] vec3 normal, 
            [In] vec3 aPosition)
        {
            vec4 ambient; vec4 diffuse; vec4 specular;
            ambient = lightAmbient;
            vec3 normalTarget = aPosition + normal;
            vec3 newNormal = (uMMatrix * new vec4(normalTarget, 1)).xyz - (uMMatrix * new vec4(aPosition, 1)).xyz;
            newNormal = normalize(newNormal);
            vec3 eye = normalize(uCamera - (uMMatrix * new vec4(aPosition, 1)).xyz);
            vec3 vp = normalize(lightLocation - (uMMatrix * new vec4(aPosition, 1)).xyz);
            vp = normalize(vp);
            vec3 halfVector = normalize(vp + eye);
            float shininess = 50.0f;
            float nDotViewPosition = max(0.0f, dot(newNormal, vp));
            diffuse = lightDiffuse * nDotViewPosition;
            float nDotViewHalfVector = dot(newNormal, halfVector);
            float powerFactor = max(0.0f, pow(nDotViewHalfVector, shininess));
            specular = lightSpecular * powerFactor;
            return ambient + diffuse + specular;
        }
    }

    public struct BufferVals
    {
        public vec4 uCamera;
        public vec4 lightPosition;
        public vec4 lightAmbient;
        public vec4 lightDiffuse;
        public vec4 lightSpecular;
    }
    public struct ConstantVals
    {
        public mat4 mvp;
        public mat4 mm;
    }
}
